/**
 * 简易持久存储工具（基于 localStorage）
 * 适合存储简单的数据，大数据量的内容应使用 @gnlab/utils/env-browser/db
 */
import { getLogger } from '@gnlab/utils'

const logger = getLogger('lib/storage')

export default class StorageManager<T> {
  topic: string
  version: number
  defaults: T
  session: boolean
  _data: undefined | T

  constructor(params: { topic: string; defaults: T; version?: number; session?: boolean }) {
    const { topic, defaults, version = 1, session = false } = params
    this.topic = topic
    this.version = version
    this.defaults = defaults
    this.session = session
    this.clearPrevVersions()
  }

  get nativeStorage() {
    return this.session ? window.sessionStorage : window.localStorage
  }

  get key() {
    return `${this.topic}-v${this.version}`
  }

  get data() {
    return typeof this._data === 'undefined' ? this.extract() : this._data
  }

  save(data: T) {
    this._data = data
    this.nativeStorage.setItem(this.key, JSON.stringify(data))
  }

  extract() {
    const key = this.key
    const raw = this.nativeStorage.getItem(key)
    if (raw === null) return this.defaults

    try {
      return JSON.parse(raw) as T
    } catch (e) {
      logger.error('数据不合法，返回默认值', { key, raw, error: e })
      return this.defaults
    }
  }

  clear() {
    this.nativeStorage.removeItem(this.key)
  }

  clearPrevVersions() {
    const prefix = `qywx-${this.topic}-`
    const prefixWithVer = `${prefix}v${this.version}`
    Object.keys(this.nativeStorage).forEach(key => {
      if (key.startsWith(prefix) && !key.startsWith(prefixWithVer)) {
        logger.info('清理老版本数据', key)
        this.nativeStorage.removeItem(key)
      }
    })
  }
}

/**
 * data 是 { key: value } 形式的 storage
 */
export class KVStorageManager<T> extends StorageManager<Record<string, T>> {
  get(key: string): T | undefined {
    return this.data[key]
  }

  set(key: string, value: T) {
    this.save({ ...this.data, [key]: value })
  }
}
